package com.yugao.fintech.antelope.codegen.manager;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.yugao.fintech.antelope.codegen.mapper.GenTableColumnMapper;
import com.yugao.fintech.antelope.codegen.model.entity.GenTable;
import com.yugao.fintech.antelope.codegen.model.entity.GenTableColumn;
import com.yugao.fintech.framework.assistant.utils.exception.Assert;
import com.yugao.fintech.framework.assistant.utils.exception.BizException;
import org.apache.commons.collections.CollectionUtils;
import org.springframework.stereotype.Repository;

import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;


@Repository
public class GenTableColumnManager extends ServiceImpl<GenTableColumnMapper, GenTableColumn>
        implements IService<GenTableColumn> {

    public void saveColumnBatch(GenTable genTable, List<GenTableColumn> columns) {
        Long tableId = genTable.getId();
        Assert.notNull(tableId, "tableId is null");
        LambdaQueryWrapper<GenTableColumn> wrapper = GenTableColumn.lqw()
                .eq(GenTableColumn::getTableId, tableId);
        for (GenTableColumn column : columns) {
            Boolean isPk = column.getIsPk();
            if (Objects.nonNull(isPk) && isPk) {
                column.setIsInsert(false);
                column.setIsEdit(true);
                column.setIsQuery(false);
                column.setIsList(true);
            }

            column.setTableId(tableId);
        }
        List<GenTableColumn> existColumns = this.list(wrapper);
        if (existColumns.isEmpty()) {
            this.saveBatch(columns);
        } else {
            Map<String, GenTableColumn> columnFromDbMap = existColumns.stream()
                    .collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity(), (k1, k2) -> k1));
            Map<String, GenTableColumn> columnFromReqMap = columns.stream()
                    .collect(Collectors.toMap(GenTableColumn::getColumnName, Function.identity(), (k1, k2) -> k1));
            List<GenTableColumn> updateColumns = columns.stream()
                    .filter(x -> columnFromDbMap.containsKey(x.getColumnName())).peek( x ->
                            x.setId(columnFromDbMap.get(x.getColumnName()).getId())
                    ).collect(Collectors.toList());

            List<GenTableColumn> saveColumns = columns.stream()
                    .filter(x -> !columnFromDbMap.containsKey(x.getColumnName())).collect(Collectors.toList());

            List<Long> deleteColumnIds = existColumns.stream()
                    .filter(x -> !columnFromReqMap.containsKey(x.getColumnName()))
                    .map(GenTableColumn::getId).collect(Collectors.toList());
            if (CollectionUtils.isNotEmpty(updateColumns)) {
                Assert.isTrue(this.updateBatchById(updateColumns), "更新失败");
            }
            if (CollectionUtils.isNotEmpty(saveColumns)) {
                Assert.isTrue(this.saveBatch(saveColumns), "更新失败");
            }
            if (CollectionUtils.isNotEmpty(deleteColumnIds)) {
                Assert.isTrue(this.removeByIds(deleteColumnIds), "更新失败");
            }
        }
    }

    public List<GenTableColumn> listByTableId(Long tableId) {
        if (Objects.isNull(tableId)) {
            return new ArrayList<>();
        }
        LambdaQueryWrapper<GenTableColumn> wrapper = GenTableColumn.lqw()
                .eq(GenTableColumn::getTableId, tableId).orderByAsc(GenTableColumn::getSort);
        return this.list(wrapper);
    }

    public void removeByTableIds(List<Long> tableIds) {
        LambdaQueryWrapper<GenTableColumn> wrapper = GenTableColumn.lqw()
                .in(GenTableColumn::getTableId, tableIds);
        if (!this.remove(wrapper)) {
            throw new BizException("删除表列失败");
        }
    }

    public void deleteBatchByTableIds(List<Long> tableIds) {
        LambdaQueryWrapper<GenTableColumn> wrapper = GenTableColumn.lqw()
                .in(GenTableColumn::getTableId, tableIds);
        this.remove(wrapper);
    }
}
